import { Injectable } from '@nestjs/common';
import { CreateRoleDto } from './dto/create-role.dto';
import { UpdateRoleDto } from './dto/update-role.dto';
import { InjectRepository } from '@nestjs/typeorm';
import { Repository, In, Brackets } from 'typeorm';
import { Role } from './entities/role.entity';
import { QueryRoleDto } from './dto/query-role.dto';
import { isEmptyStr } from 'src/common/utils/common';
import { PageResultDto } from 'src/common/dto';
import { UpdateRoleMenusDto } from './dto/role-menu.dto';
import { Menu } from '../menu/entities/menu.entity';
@Injectable()
export class RoleService {
  constructor(
    @InjectRepository(Role)
    private roleRepository: Repository<Role>
  ) {}
  async create(createRoleDto: CreateRoleDto) {
    try{
      let role = this.roleRepository.create(createRoleDto);
      let result = await this.roleRepository.save(role);
      console.log(result);
      if(result){
        return [true,  '角色创建成功'];
      }
    }
    catch (error) {
      console.error('创建角色失败:', error.message);
      return [false, error.message];
    }
  }

  async update(updateRoleDto: UpdateRoleDto) {
    try{
      const role = await this.roleRepository.create(updateRoleDto);
      await this.roleRepository.save(role);
      return [true, '角色更新成功'];
    } catch (error) {
      console.error('Error updating role:', error);
      return [false, '角色更新失败'];
    }
  }

  async remove(IdArr: Array<string>) {
    try {
      await this.roleRepository.update(
              { Id: In(IdArr) },{ deleted: 1 }
            );
      return [true, '角色删除成功'];
    } catch (error) {
      console.error('Error deleting role:', error);
      return [false, '角色删除失败'];
    }
  }

  async GetRoleList(query: any, tenantId: string){
    try{
      let roles = await this.roleRepository.createQueryBuilder('role')
      .where('role.Deleted = :Deleted', { Deleted: 0 })
      .andWhere(new Brackets(qb => {
        if (!isEmptyStr(query.name)) {
          qb.andWhere('role.name LIKE :Name', { name: `%${query.name}%` });
        }
      }))
      .andWhere('role.tenantId = :tenantId', { tenantId: tenantId })
      .skip((query.current - 1) * query.size)
      .take(query.current)
      .getMany();
      
      let result = new PageResultDto<Role>();
      result.data = roles;
      result.total = await this.roleRepository.count();
      result.pageNum = query.pageNum;
      result.pageSize = query.pageSize;
      return result;
    } catch (error) {
      console.error('Error fetching role list:', error);
      return new PageResultDto<Role>();
    }
  }

  async getMenusByRoleId(roleId: string){
    let roleData = await this.roleRepository.createQueryBuilder('role')
                                            .leftJoinAndSelect('role.Menus', 'Menus') 
                                            .where('role.Id = :roleId ', { roleId })
                                            .andWhere('Menus.IsShow = :isShow', { isShow: 1 })
                                            .andWhere('Menus.Deleted = :Deleted', { Deleted: 0 })
                                            .andWhere('role.Deleted = :deleted', { deleted: 0 })
                                            .orderBy('Menus.Sort', 'ASC')
                                            .getMany();
    if(roleData.length != 0) {
      let menus = roleData[0].Menus;
      return this.flatArrayToTree(menus);
    }
    return [];
  }

  async getFlatMenusByRoleId(roleId: string){
    let roleData = await this.roleRepository.createQueryBuilder('role')
                                            .leftJoinAndSelect('role.Menus', 'Menus') 
                                            .where('role.Id = :roleId ', { roleId })
                                            .andWhere('Menus.IsShow = :isShow', { isShow: 1 })
                                            .andWhere('Menus.Deleted = :Deleted', { Deleted: 0 })
                                            .andWhere('role.Deleted = :deleted', { deleted: 0 })
                                            .orderBy('Menus.Sort', 'ASC')
                                            .getMany();
    if(roleData.length != 0) {
      let menus = roleData[0].Menus.map( item => {
        if(item.isParent == 0){
          return item.Id
        }
        
      })
      return menus
    }
    return [];
  }

  async UpdateRoleMenus(params: UpdateRoleMenusDto){
    try{
      let menus = [];
      for(let i = 0; i < params.Menus.length; i ++){
        let item = new Menu();
        item.Id = params.Menus[i];
        menus.push(item);
      }
      let role = new Role();
      role.Id = params.Id;
      role.Menus = menus;
      await this.roleRepository.save(role);
      return [true, '权限修改成功']
    }catch(err){
      console.log(err);
      return [false, '权限修改失败']
    }
  }

  flatArrayToTree(menus) {
  // 创建一个映射，方便通过id查找节点
    const map = new Map();
    menus.forEach(item => {
      map.set(item.Id, { ...item, children: [] });
    });

    // 定义一个递归函数，用于构建每个节点的子树
    function buildTree(node) {
      menus.forEach(item => {
        if (item.Pid === node.Id) {
          const childNode = map.get(item.Id);
          // 递归构建子树，并添加到当前节点的children中
          node.children.push(buildTree(childNode)); 
        }
      });
      return node;
    }

    // 过滤出根节点并递归构建整棵树
    return menus
      .filter(item => item.Pid === "0")
      .map(rootNode => buildTree(map.get(rootNode.Id)));
  }
}
